package com.ynding;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
/**
 * @author Administrator
 */
public class Driver extends Applet implements Runnable, MouseMotionListener, MouseListener
{
	Particle[] p;//定义一个Particle对象p
	Graphics memScreen;
	Image memImage;
	int NUM_BOIDS = 50;
	int WIDTH = 640;
	int HEIGHT = 480;
	long fps, frames, firstFrame;
	int mx, my;
	boolean mouseIn = false;
	//初始化
	public void init()
	{
		memImage = createImage( WIDTH, HEIGHT );
		memScreen = memImage.getGraphics();
		//实例化对象p
		p = new Particle[NUM_BOIDS];
		//初始化对象p
		for(int i = 0; i < NUM_BOIDS; i++)
		{
			p[i] = new Particle();
			p[i].initialize(WIDTH/2, HEIGHT/2);
		}
		addMouseMotionListener(this);
		addMouseListener(this);
		Thread t = new Thread(this);
		t.start();
	}
	//开始
	public void start()
	{
		firstFrame=System.currentTimeMillis();
		frames = 0;
	}
	//运行
	public void run()
	{
		float[] v1 = new float[2];
		float[] v2 = new float[2];
		float[] v3 = new float[2];
		float[] v4 = new float[2];
		float[] v5 = new float[2];
		while(true)
		{
			try
			{
				Thread.sleep(20);
				for(int i = 0; i<NUM_BOIDS; i++)
				{
					v1 = moveto_cent_of_mass(i);
					v2 = check_distance(i);
					v3 = match_velocity(i);
					v4 = check_bounds(i);
					v5 = follow_leader(i);
					p[i].update(v1, v2, v3, v4, v5, i, mouseIn);
				}
			}
			catch(Exception e){}
			repaint();
		}
	}
	//follow_leader方法，实现跟随领导颗粒的规则
	public float[] follow_leader(int curr_boid)
	{
		float[] v = new float[2];
		if(!mouseIn && curr_boid!=0)
		{
			v[0] = (p[0].x - p[curr_boid].x)/1000.0f;
			v[1] = (p[0].y - p[curr_boid].y)/1000.0f;
		}
		else if(!mouseIn && curr_boid==0)
		{
			v[0] = (p[curr_boid].x - p[1].x)/1000.0f;
			v[1] = (p[curr_boid].y - p[1].y)/1000.0f;
		}
		if(mouseIn)
		{
			v[0] = (mx - p[curr_boid].x)/1000.0f;
			v[1] = (my - p[curr_boid].y)/1000.0f;
		}
		return v;
	}
	//check_bounds方法，负责检测是否到达边界
	public float[] check_bounds(int curr_boid)
	{
		float[] v = new float[2];
		if(p[curr_boid].x < 0)
			v[0] = 1.0f;
		else if(p[curr_boid].x > 640)
			v[0] = -1.0f;
		if(p[curr_boid].y < 0)
			v[1] = 1.0f;
		else if(p[curr_boid].y > 480)
			v[1] = -1.0f;
		return v;
	}
	//moveto_cent_of_mass方法，实现尽量占据蜂群中心位置规则
	public float[] moveto_cent_of_mass(int curr_boid)
	{
		float[] v = new float[2];
		for(int i = 0; i < NUM_BOIDS; i++)
		{
			if(i!=curr_boid)
			{
				v[0]+=p[i].x;
				v[1]+=p[i].y;
			}
		}
		v[0]=(v[0]/(NUM_BOIDS-1));
		v[1]=(v[1]/(NUM_BOIDS-1));
		v[0] = (v[0] - p[curr_boid].x) / 700.0f;
		v[1] = (v[1] - p[curr_boid].y) / 700.0f;
		return v;
	}
	//check_distance方法，负责测试与其他颗粒间的距离
	public float[] check_distance(int curr_boid)
	{
		float[] v = new float[2];
		for(int i = 0; i < NUM_BOIDS; i++)
		{
			if(i!=curr_boid)
			{
				if(Math.abs(p[curr_boid].x - p[i].x) < 0.8f)
				{
					v[0]-=((p[curr_boid].x - p[i].x));
				}
				if(Math.abs(p[curr_boid].y - p[i].y) < 0.8f)
				{
					v[1]-=((p[curr_boid].y - p[i].y));
				}
			}
		}
		return v;
	}
	//match_velocity方法，实现与其他颗粒保持相同速度的规则
	public float[] match_velocity(int curr_boid)
	{
		float[] v = new float[2];
		for(int i = 0; i < NUM_BOIDS; i++)
		{
			if(i!=curr_boid)
			{
				v[0]+=p[i].velocityX;
				v[1]+=p[i].velocityY;
			}
		}
		v[0]=((v[0]/(NUM_BOIDS-1))/700.0f);
		v[1]=((v[1]/(NUM_BOIDS-1))/700.0f);
		return v;
	}
	//update方法
	public void update(Graphics gr)
	{
		paint(gr);
	}
	//paint方法，负责在屏幕上输出运行结果
	public void paint(Graphics gr)
	{
		memImage.flush();
		memScreen.setColor(Color.black);
		memScreen.fillRect(0,0,WIDTH,HEIGHT);
		memScreen.setColor(Color.green);
		for(int i = 0; i < NUM_BOIDS; i++)
		{
			memScreen.fillRect((int)p[i].x, (int)p[i].y, 3, 3);
			memScreen.setColor(Color.white);
		}
		frames++;
		fps = (frames*10000) / (System.currentTimeMillis()-firstFrame);
		memScreen.setColor(Color.white);
		memScreen.drawString(fps/10 + "." + fps%10 + " fps", 2, HEIGHT - 2);
		gr.drawImage(memImage,0,0,this);
	}
	//处理鼠标移动事件
	public void mouseMoved(MouseEvent e)
	{
		mx = e.getX();
		my = e.getY();
	}
	//处理鼠标进入事件
	public void mouseEntered(MouseEvent e)
	{
		mouseIn = true;
	}
	//处理鼠标移出事件
	public void mouseExited(MouseEvent e)
	{
		mouseIn = false;
	}
	//处理其他鼠标事件
	public void mouseClicked(MouseEvent e){}
	public void mousePressed(MouseEvent e){}
	public void mouseReleased(MouseEvent e){}
	public void mouseDragged(MouseEvent e)
	{
	}
}
